AWS Amplify iOSで画像からオブジェクトを検出する #reinvent
RekognitionとCoreMLを併用し、画像からオブジェクトを検出しよう
re:Invent 2019の期間中、ネイティブアプリ用の新しいSDKAmplify iOSとAmplify Androidがプレビューにて公開されました。
その中で、iOSでは Prediction(予測機能) について CoreMLフレームワークとの組み合わせ が実装されています。ML/AI系の機能を、AWSサービスとiOS Frameworkを組み合わせ、非常に高い精度の結果セットが得られるようになっています。
CoreMLフレームワークおよびCoreML VisionフレームワークはiOSの機械学習用のフレームワークで、学習モデルなどを扱う際に開発者が専門的な知識を必要とせずに扱えるように補助するフレームワークです。CPU、GPU、ニューラルエンジンを活用し、予測の作成、モデルのトレーニングや微調整をすべてユーザーのデバイス上で行うようになっています。
本記事では、Amplify iOSを使って画像からオブジェクトを検出する機能を試してみました。
AWSサービスとしてはAmazon Rekognitionを利用する形となります。Amplify iOSを通して使うことで、ローカル(オフライン)での実行も可能になります。
インストール
それではまずはインストールしていきます。なお、AmplifyのiOSアプリ向けプロジェクトはすでに作成済みの前提で進めます。また、今回は対話形式でのインストールが必要なためAmplify CLIを利用します。
まずは predictions
というプラグインを追加します。
$ amplify add predictions
対話形式で、どのような機能を作りたいか問われます。
? Please select from one of the categories below : Identify ? What would you like to identify? : Identify Labels ? Provide a friendly name for your resource : identifyLabels6d3324c5 ? Would you like use the default configuration? : Default Configuration ? Who should have access? : Auth and Guest users
Prediction機能は以下のように分類されているので、自分の作りたい機能に合わせて設定します。本記事では Identify
を選択しています。
? Please select from one of the categories below ❯ Identify Convert Interpret Infer Learn More
Identify
を選択すると ? What would you like to identify?
と、どのような種類の解釈を行いたいのか問われます。今回は Identify Labels
としました。
? What would you like to identify? Identify Text Identify Entities ❯ Identify Labels
また、最後の Who should have access?
は Auth and Guest users
を選び、Cognito User Poolsの作成を行うようにします。これはAWSリソースへのアクセスを行うため必須になります。
Successfully added resource identifyLabels6d3324c5 locally
ローカルでの設定が完了したので amplify push
でAWSリソースを作成します。
$ amplify push | Category | Resource name | Operation | Provider plugin | | ----------- | ---------------------- | --------- | ----------------- | | Predictions | identifyLabels6d3324c5 | Create | awscloudformation | | Api | amplifyDatasource | No Change | awscloudformation | | Auth | amplifysample93d65ae8 | No Change | awscloudformation |
以上でAWSリソースの作成は完了です。
次に AWSPredictionsPlugin
というPodを追加します。Podfile
全体としては以下のようになります。
target 'AmplifySample' do # Comment the next line if you don't want to use dynamic frameworks use_frameworks! # Pods for AmplifySample pod 'amplify-tools' pod 'Amplify' pod 'AWSPluginsCore' pod 'AWSPredictionsPlugin' pod 'AWSMobileClient', '~> 2.12.0' pod 'AmplifyPlugins/AWSAPIPlugin' end
最後に pod install
を実行して終わりです。
$ pod install --repo-update
実装
今回は画像からオブジェクトの検出を行いたいだけなので、iOSアプリでは画面なしで実装します。
まずは AppDelegate
でセットアップする処理を書きます。
import UIKit import Amplify import AWSPredictionsPlugin import AmplifyPlugins @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { let apiPlugin = AWSAPIPlugin(modelRegistration: AmplifyModels()) let predictionsPlugin = AWSPredictionsPlugin() do { try Amplify.add(plugin: apiPlugin) try Amplify.add(plugin: predictionsPlugin) try Amplify.configure() print("Amplify initialized") } catch { print("Failed to configure Amplify \(error)") } return true } }
次に ViewController
で画像からオブジェクトの検出を行う処理を実装します。detectLabels()
というメソッドを用意しました。
import UIKit import Amplify class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() detectLabels() } func detectLabels() { guard let path = Bundle.main.path(forResource: "sample-image-room", ofType: "jpg") else { return } let image = URL(fileURLWithPath: path) let options = PredictionsIdentifyRequest.Options(defaultNetworkPolicy: .auto, uploadToRemote: false) _ = Amplify.Predictions.identify(type: .detectLabels(.labels), image: image, options: options, listener: { (event) in switch event { case .completed(let result): let data = result as! IdentifyLabelsResult print(data) case .failed(let error): print(error) default: print("") } }) } }
対象の画像は URL
型で指定します。ローカルまたはWeb上の画像から指定します。上記は sample-image-room.jpg
という画像ファイルをXcodeプロジェクト内に追加した場合のコードです。オフラインでの動作を試したい場合はXcodeプロジェクトに追加するようにしてください。
試してみる
それでは実行してみましょう。写真は以下のような写真を使いました。Pexels の Pixabayさんによる写真をいただきました。御礼申し上げます。
コンソールログに以下のように出力されるかと思います(見やすいようにインデントなどを整形しています)。家具、テーブル、植物などが検出できていることが分かります。
IdentifyLabelsResult( labels: [ Amplify.Label(name: "Structure", metadata: Optional(Amplify.LabelMetadata(confidence: 94.7685317993164, parents: nil)), boundingBoxes: nil), Amplify.Label(name: "Furniture", metadata: Optional(Amplify.LabelMetadata(confidence: 92.10990142822266, parents: nil)), boundingBoxes: nil), Amplify.Label(name: "Table", metadata: Optional(Amplify.LabelMetadata(confidence: 92.10356140136719, parents: nil)), boundingBoxes: nil), Amplify.Label(name: "Plant", metadata: Optional(Amplify.LabelMetadata(confidence: 85.46121978759766, parents: nil)), boundingBoxes: nil) ], unsafeContent: nil )
結果は IdentifyLabelsResult 型で返されます。それぞれ次のような意味があります。
要素 | 説明 |
---|---|
labels |
画像から検出されたLabel情報の配列 |
unsafeContent |
安全ではないコンテンツが含まれているかどうか |
明示的にオフラインで使いたい場合は、実行する際のオプション設定を変更します。
let options = PredictionsIdentifyRequest.Options(defaultNetworkPolicy: .offline, uploadToRemote: false)
画像からスピーディにオブジェクトを検出する仕組みを作ろう
本記事で紹介した昨日はオンライン/オフライン問わず利用できるので、例えば「写真から画像を検索する」機能をアプリで実装するときなどに利用できます。ポイントはローカルだけで完結させることもできる点です。Rekognitionを使っているような感覚でCoreMLフレームワークを利用できるのは嬉しいですね。